package com.blacktry.GATest;

import java.util.HashMap;

// 已验
public class Timetable {
    // 已验
    private final HashMap<Long, Room> rooms;
    private final HashMap<Long, Professor> professors;
    private final HashMap<Long, Module> modules;
    private final HashMap<Long, Group> groups;
    private final HashMap<Long, Timeslot> timeslots;
    private Class classes[];

    private int numClasses = 0;

    // 已验
    public Timetable() {
        this.rooms = new HashMap<Long, Room>();
        this.professors = new HashMap<Long, Professor>();
        this.modules = new HashMap<Long, Module>();
        this.groups = new HashMap<Long, Group>();
        this.timeslots = new HashMap<Long, Timeslot>();
    }

    // 已验
    public Timetable(Timetable cloneable) {
        this.rooms = cloneable.getRooms();
        this.professors = cloneable.getProfessors();
        this.modules = cloneable.getModules();
        this.groups = cloneable.getGroups();
        this.timeslots = cloneable.getTimeslots();
    }

    // 已验
    private HashMap<Long, Group> getGroups() {
        return this.groups;
    }

    // 已验
    private HashMap<Long, Timeslot> getTimeslots() {
        return this.timeslots;
    }

    // 已验
    private HashMap<Long, Module> getModules() {
        return this.modules;
    }

    // 已验
    private HashMap<Long, Professor> getProfessors() {
        return this.professors;
    }

    // 已验
    public void addRoom(long roomId, String roomName, long capacity) {
        this.rooms.put(roomId, new Room(roomId, roomName, capacity));
    }

    // 已验
    public void addProfessor(long professorId, String professorName) {
        this.professors.put(professorId, new Professor(professorId, professorName));
    }

    // 已验
    public void addModule(long moduleId, String moduleCode, String module, long professorIds[]) {
        this.modules.put(moduleId, new Module(moduleId, moduleCode, module, professorIds));
    }

    // 已验
    public void addGroup(long groupId, long groupSize, long moduleIds[]) {
        this.groups.put(groupId, new Group(groupId, groupSize, moduleIds));
        this.numClasses = 0;
    }

    // 已验
    public void addTimeslot(long timeslotId, String timeslot) {
        this.timeslots.put(timeslotId, new Timeslot(timeslotId, timeslot));
    }

    // 已验
    public void createClasses(Individual individual) {
        Class classes[] = new Class[this.getNumClasses()];

        long chromosome[] = individual.getChromosome();
        int chromosomePos = 0;
        int classIndex = 0;

        for (Group group : this.getGroupsAsArray()) {
            long moduleIds[] = group.getModuleIds();
            for (long moduleId : moduleIds) {
                classes[classIndex] = new Class(classIndex, group.getGroupId(), moduleId);
                classes[classIndex].addTimeslot(chromosome[chromosomePos]);
                chromosomePos++;
                classes[classIndex].setRoomId(chromosome[chromosomePos]);
                chromosomePos++;
                classes[classIndex].addProfessor(chromosome[chromosomePos]);
                chromosomePos++;

                classIndex++;
            }
        }
        this.classes = classes;
    }

    // 已验
    public Room getRoom(long roomId) {
        if (!this.rooms.containsKey(roomId)) {
            System.out.println("Rooms doesn't contain key " + roomId);
        }
        return (Room) this.rooms.get(roomId);
    }

    // 已验
    public HashMap<Long, Room> getRooms() {
        return this.rooms;
    }

    // 已验
    public Room getRandomRoom() {
        Object[] roomsArray = this.rooms.values().toArray();
        Room room = (Room) roomsArray[(int) (roomsArray.length * Math.random())];
        return room;
    }

    // 已验
    public Professor getProfessor(long professorId) {
        return (Professor) this.professors.get(professorId);
    }

    // 已验
    public Module getModule(long moduleId) {
        return (Module) this.modules.get(moduleId);
    }

    // 已验
    public long[] getGroupModules(long groupId) {
        Group group = (Group) this.groups.get(groupId);
        return group.getModuleIds();
    }

    // 已验
    public Group getGroup(long groupId) {
        return (Group) this.groups.get(groupId);
    }

    // 已验
    public Group[] getGroupsAsArray() {
        return (Group[]) this.groups.values().toArray(new Group[this.groups.size()]);
    }

    // 已验
    public Timeslot getTimeslot(long timeslotId) {
        return (Timeslot) this.timeslots.get(timeslotId);
    }

    // 已验
    public Timeslot getRandomTimeslot() {
        Object[] timeslotArray = this.timeslots.values().toArray();
        Timeslot timeslot = (Timeslot) timeslotArray[(int) (timeslotArray.length * Math.random())];
        return timeslot;
    }

    // 已验
    public Class[] getClasses() {
        return this.classes;
    }

    // 已验
    public int getNumClasses() {
        if (this.numClasses > 0) {
            return this.numClasses;
        }
        int numClasses = 0;
        Group groups[] = (Group[]) this.groups.values().toArray(new Group[this.groups.size()]);
        for (Group group : groups) {
            numClasses += group.getModuleIds().length;
        }
        this.numClasses = numClasses;
        return this.numClasses;
    }

    // 计算冲突，如果违反了硬约束就clashes++  // 已验
    public int calcClashes() {
        int clashes = 0;
        for (Class classA : this.classes) {
            // 检查教室容量
            long roomCapacity = this.getRoom(classA.getRoomId()).getRoomCapacity();
            long groupSize = this.getGroup(classA.getGroupId()).getGroupSize();
            if (roomCapacity < groupSize) {
                clashes++;
            }
            // 查看教室是否被占用
            for (Class classB : this.classes) {
                if (classA.getRoomId() == classB.getRoomId() && classA.getTimeslotId() == classB.getTimeslotId()
                        && classA.getClassId() != classB.getClassId()) {
                    clashes++;
                    break;
                }
            }
            // 查看教授是否有空
            for (Class classB : this.classes) {
                if (classA.getProfessorId() == classB.getProfessorId()
                        && classA.getTimeslotId() == classB.getTimeslotId()
                        && classA.getClassId() != classB.getClassId()) {
                    clashes++;
                    break;
                }
            }
        }
        return clashes;
    }
}



